// 可见性下拉框（通用在：新建组和库、url导入）
import React from 'react';
import PropTypes from 'prop-types';
import { Select } from '@teamix/ui';
import { ENUM } from 'utils/constants.js';
import Overlay from './overlay.jsx';
import './index.scss';
import exceed from 'utils/apimap';
import KEYCODE from 'utils/keycode';
import intl from '../../locale';

const { organization } = window.FORCE;

function preventDefault(e) {
  e.preventDefault();
}

export default class CreateAccessSelect extends React.Component {
  static propTypes = {
    onChange: PropTypes.func,
    // 组的可见性
    groupAccess: PropTypes.string,
    // 请求回来给表单设置默认值
    initValueFn: PropTypes.func,
    // 组库标识：是否为库
    isRepo: PropTypes.bool,
  };

  static defaultProps = {
    onChange: () => {},
    groupAccess: '',
    initValueFn: () => {},
    isRepo: true,
  };

  constructor(props) {
    super(props);
    this.state = {
      isLevelPopVisible: false,
      visibility_level: '',
      visibility_levels: [
        {
          value: ENUM.visibility_level.PRIVATE,
          label: this.props.isRepo
            ? intl.get({
                id: 'code-assets.components.accessSelect.PrivateVisibleOnlyToMembers',
                defaultMessage: '私有(仅代码库成员可见)',
              })
            : intl.get({
                id: 'code-assets.components.accessSelect.PrivateVisibleOnlyToCode',
                defaultMessage: '私有(仅代码组成员可见)',
              }),
          des: this.props.isRepo
            ? intl.get({
                id: 'code-assets.components.accessSelect.VisibleOnlyToMembersOf',
                defaultMessage: '仅代码库成员可见',
              })
            : intl.get({
                id: 'code-assets.components.accessSelect.VisibleOnlyToCodeGroup',
                defaultMessage: '仅代码组成员可见',
              }),
          title: intl.get({
            id: 'code-assets.components.accessSelect.Private',
            defaultMessage: '私有',
          }),
          tip: intl.get({
            id: 'code-assets.components.accessSelect.TheEnterpriseDoesNotSupport',
            defaultMessage: '所属企业不支持该公开性设置，如有需要请联系企业管理员开放',
          }),
        },

        {
          value: ENUM.visibility_level.INTERNAL,
          label: intl.get({
            id: 'code-assets.components.accessSelect.VisibleToEnterpriseAccessibleTo',
            defaultMessage: '企业可见(企业内成员可访问)',
          }),
          des: intl.get({
            id: 'code-assets.components.accessSelect.EnterpriseMembersCanAccess',
            defaultMessage: '企业内成员可访问',
          }),
          title: intl.get({
            id: 'code-assets.components.accessSelect.EnterpriseVisible',
            defaultMessage: '企业可见',
          }),
          tip: intl.get({
            id: 'code-assets.components.accessSelect.TheEnterpriseDoesNotSupport',
            defaultMessage: '所属企业不支持该公开性设置，如有需要请联系企业管理员开放',
          }),
        },

        // {
        //   value: ENUM.visibility_level.PUBLIC,
        //   label: '公开(仅代码库成员可见)',
        //   des: '所有登录用户均可访问',
        //   title: '公开',
        //   tip: '受所属组公开性影响，无法选择',
        // },
      ],
      curLevels: [],
      group_visibility_level: [],
      repo_visibility_level: [],
      isLoading: true,
      highlightKey: null,
    };
  }

  componentDidMount() {
    this.setState({
      isLoading: true,
    });

    this.getSettingLevels();
  }

  componentDidUpdate(prevProps) {
    if (prevProps.groupAccess !== this.props.groupAccess) {
      const { visible_levels, display_levels } = this.state;
      this.getValue(visible_levels, display_levels);
    }
  }

  getSettingLevels() {
    // 获取公开性的设置信息
    const { isRepo } = this.props;
    exceed
      .forceFetch({
        api: `organization.${isRepo ? 'repo' : 'group'}.setting.get`,
        params: {
          org_id: organization.id,
        },
      })
      .then((result) => {
        const visible_levels = isRepo
          ? result.repo_visibility_level || []
          : result.group_visibility_level || [];
        const display_levels = isRepo
          ? result.repo_display_level || []
          : result.group_display_level || [];
        this.setState({
          visible_levels,
          display_levels,
          isLoading: false,
          group_visibility_level: result.group_visibility_level || [],
          repo_visibility_level: result.repo_visibility_level || [],
        });

        this.getValue(visible_levels, display_levels);
      });
  }

  getValue = (visible_levels, display_levels) => {
    const { value, isRepo } = this.props;
    const { repo_visibility_level, group_visibility_level } = this.state;
    const curLevels = this.getLevels(visible_levels, display_levels);
    // 全部禁用则使用没有默认值
    const isAllDisabled = curLevels.every((item) => {
      return item.disabled;
    });
    let visibility_level;
    if (isAllDisabled) {
      visibility_level = '';
    } else {
      // 使用传入值,没有则默认
      visibility_level = value
        ? Number(value)
        : (isRepo ? repo_visibility_level[0] : group_visibility_level[0]) ||
          ENUM.visibility_level.PRIVATE;
    }

    this.setState({
      curLevels,
      visibility_level,
    });

    this.props.initValueFn(visibility_level);
  };

  handleSelect = (item) => {
    this.setState({
      isLevelPopVisible: false,
      visibility_level: item.value,
    });

    this.props.onChange(item.value);
  };

  onVisibleChange = (visible) => {
    this.setState({
      isLevelPopVisible: visible,
      highlightKey: null,
    });
  };

  getLevels = (visible_levels, display_levels) => {
    // 显示的部分
    const showLevels = this.state.visibility_levels.filter((item) => {
      return display_levels.indexOf(item.value) > -1;
    });
    const curLevels = showLevels.map((item) => {
      item.disabled =
        visible_levels.indexOf(item.value) === -1 ||
        (this.props.groupAccess && Number(this.props.groupAccess) < item.value);
      // 组限制，文案修改
      if (
        visible_levels.indexOf(item.value) !== -1 &&
        this.props.groupAccess &&
        Number(this.props.groupAccess) < item.value
      ) {
        const name = this.props.isRepo
          ? intl.get({
              id: 'code-assets.components.accessSelect.CodeBase',
              defaultMessage: '代码库',
            })
          : intl.get({
              id: 'code-assets.components.accessSelect.CodeGroup',
              defaultMessage: '代码组',
            });
        item.tip = intl.get(
          {
            id: 'code-assets.components.accessSelect.ThePublicityOfTheParent',
            defaultMessage: '所属父代码组的公开性是私有，{name}的公开性必须设置私有',
          },
          { name },
        );
      }
      return item;
    });
    return curLevels;
  };

  handleKeyDown = (e) => {
    const { isLevelPopVisible, curLevels, highlightKey } = this.state;
    switch (e.keyCode) {
      case KEYCODE.UP:
        e.preventDefault();
        this.toggleHighlightItem(-1, e);
        break;
      case KEYCODE.DOWN:
        e.preventDefault();
        this.toggleHighlightItem(1, e);
        break;
      case KEYCODE.ENTER:
        e.preventDefault();
        if (isLevelPopVisible) {
          const highlightItem = curLevels.find((item) => item.value === highlightKey);
          highlightItem && this.handleSelect(highlightItem);
        } else {
          this.setState({
            isLevelPopVisible: true,
          });
        }
        break;
      case KEYCODE.ESC:
        e.preventDefault();
        this.setState({
          isLevelPopVisible: false,
        });

        break;
      default:
        break;
    }
  };

  toggleHighlightItem = (dir) => {
    const { curLevels } = this.state;
    if (!this.state.isLevelPopVisible) {
      this.setState({
        isLevelPopVisible: true,
      });

      return;
    }

    const enabledData = curLevels.filter((item) => !item.disabled);
    const maxCount = enabledData.length;
    // When there is no enabled item
    if (!maxCount) {
      return false;
    }

    let { highlightKey } = this.state;
    let highlightIndex = -1;

    // find previous highlight index
    highlightKey !== null &&
      enabledData.some((item, index) => {
        if (item.value === highlightKey) {
          highlightIndex = index;
        }
        return highlightIndex > -1;
      });

    // toggle highlight index
    highlightIndex += dir;
    if (highlightIndex < 0) {
      highlightIndex = maxCount - 1;
    }
    if (highlightIndex >= maxCount) {
      highlightIndex = 0;
    }

    // get highlight key
    const highlightItem = enabledData[highlightIndex];
    highlightKey = highlightItem ? highlightItem.value : null;

    this.setState({
      highlightKey,
    });
  };

  render() {
    const { isLoading, curLevels, visibility_level, highlightKey } = this.state;

    const visibilityPopupContent = (
      <Overlay
        onChange={this.handleSelect}
        onMouseDown={preventDefault}
        selectValue={visibility_level}
        data={curLevels}
        isOverlayLoading={isLoading}
        // 高亮value
        highlightKey={highlightKey}
      />
    );

    const popupProps = {
      triggerClickKeycode: [13, 32], // space, enter, down-arrow
    };

    return (
      <Select
        {...this.props}
        visible={this.state.isLevelPopVisible}
        onVisibleChange={this.onVisibleChange}
        value={isLoading ? '' : visibility_level}
        popupProps={popupProps}
        popupContent={visibilityPopupContent}
        dataSource={isLoading ? [] : curLevels}
        onKeyDown={this.handleKeyDown}
      />
    );
  }
}
